package cn.stylefeng.roses.kernel.license.listener;

import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.license.api.LicenseApi;
import cn.stylefeng.roses.kernel.license.api.constants.LicenseConstants;
import cn.stylefeng.roses.kernel.license.api.pojo.SecretDTO;
import cn.stylefeng.roses.kernel.license.api.util.MacAddressUtil;
import cn.stylefeng.roses.kernel.license.context.AlreadyInitFlag;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目license机制的监听器
 *
 * @author fengshuonan
 * @date 2020/11/13 13:08
 */
@Component
public class ValidationListener implements ApplicationListener<ApplicationContextEvent>, Ordered {

    @Resource
    private LicenseApi licenseApi;

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public void onApplicationEvent(ApplicationContextEvent event) {
        if (!AlreadyInitFlag.getAlreadyInit()) {
            validateLicense(event);
            AlreadyInitFlag.alreadyInit();
        }
    }

    private void validateLicense(ApplicationContextEvent event) {

        Environment environment = event.getApplicationContext().getEnvironment();
        String projectLicense = environment.getProperty("project.license");

        // 检验是否为空
        if (StrUtil.isEmpty(projectLicense)) {
            System.err.println("项目license未配置，请检查project.license属性是否正确配置！errorCode: 001");
            System.exit(-1);
        }

        // RSA解密，校验license的正确性
        SecretDTO secretDTO = new SecretDTO();
        secretDTO.setPrivateSecret(LicenseConstants.RSA_PRIVATE_KEY);
        secretDTO.setPublicSecret(LicenseConstants.RSA_PUBLIC_KEY);
        boolean licenseRight = licenseApi.validateLicenseStr(secretDTO, projectLicense);
        if (!licenseRight) {
            System.err.println("项目license失效！请检查项目license是否合法！errorCode: 002");
            System.exit(-1);
        }

        // 获取解密的mac地址列表
        String licenseContent = licenseApi.decryptLicense(secretDTO, projectLicense);
        JSONArray objects = JSON.parseArray(licenseContent);
        List<String> strings = objects.toJavaList(String.class);

        // 如果列表为空，则license不合法
        if (strings == null || strings.size() == 0) {
            System.err.println("项目license失效！请检查项目license是否合法！errorCode: 003");
            System.exit(-1);
        }

        // 获取本机的mac地址列表
        List<String> macList = new ArrayList<>();
        try {
            macList = MacAddressUtil.getMacList();
        } catch (Exception e) {
            System.err.println("项目license失效！请检查项目license是否合法！errorCode: 004");
            System.exit(-1);
        }

        // 比对本机和秘钥中的mac是否有匹配的，如果有匹配的则代表正确
        for (String secretMac : strings) {
            for (String localMac : macList) {
                if (secretMac.equalsIgnoreCase(localMac)) {
                    System.err.println("项目license校验成功！项目正在启动！");
                    return;
                }
            }
        }

        System.err.println("项目license不合法！若换机器请从新生成秘钥！errorCode: 005");
        System.exit(-1);
    }

}
